package com.sunwayworld.basemodule.business.batch.service.impl;

import com.sunwayworld.basemodule.business.batch.bean.LimsBatchBean;
import com.sunwayworld.basemodule.business.batch.bean.LimsBatchSampleBean;
import com.sunwayworld.basemodule.business.batch.bean.LimsBatchSampleProductBean;
import com.sunwayworld.basemodule.business.batch.dao.LimsBatchSampleDao;
import com.sunwayworld.basemodule.business.batch.service.LimsBatchSampleProductService;
import com.sunwayworld.basemodule.business.batch.service.LimsBatchSampleService;
import com.sunwayworld.basemodule.business.batch.service.LimsBatchService;
import com.sunwayworld.basemodule.coredata.product.bean.LimsProductMainBean;
import com.sunwayworld.basemodule.coredata.product.service.LimsProductMainService;
import com.sunwayworld.basemodule.samplemanage.sample.bean.LimsSampleBean;
import com.sunwayworld.basemodule.samplemanage.sample.service.LimsSampleService;
import com.sunwayworld.framework.at.annotation.AuditTrailEntry;
import com.sunwayworld.framework.at.annotation.AuditTrailType;
import com.sunwayworld.framework.audit.aunnotation.Audit;
import com.sunwayworld.framework.audit.constant.AuditConstant;
import com.sunwayworld.framework.constant.Constant;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.data.page.Page;
import com.sunwayworld.framework.exception.InvalidDataException;
import com.sunwayworld.framework.mybatis.mapper.MapperParameter;
import com.sunwayworld.framework.mybatis.mapper.MatchPattern;
import com.sunwayworld.framework.mybatis.mapper.SearchFilter;
import com.sunwayworld.framework.mybatis.page.MybatisPageHelper;
import com.sunwayworld.framework.mybatis.page.PageRowBounds;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;
import com.sunwayworld.framework.spring.annotation.GikamBean;
import com.sunwayworld.framework.support.PersistableHelper;
import com.sunwayworld.framework.utils.NumberUtils;
import com.sunwayworld.framework.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Repository
@GikamBean
public class LimsBatchSampleServiceImpl implements LimsBatchSampleService {

    @Autowired
    private LimsBatchSampleDao limsBatchSampleDao;

    @Lazy
    @Autowired
    private LimsBatchService batchService;

    @Lazy
    @Autowired
    private LimsSampleService sampleService;

    @Lazy
    @Autowired
    private LimsBatchSampleProductService sampleProductService;

    @Lazy
    @Autowired
    private LimsProductMainService productMainService;

    @Override
    @SuppressWarnings("unchecked")
    public LimsBatchSampleDao getDao() {
        return limsBatchSampleDao;
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.INSERT)
    public Long insert(RestJsonWrapperBean jsonWrapper) {
        LimsBatchSampleBean limsBatchSample = jsonWrapper.parseUnique(LimsBatchSampleBean.class);
        limsBatchSample.setId(ApplicationContextHelper.getNextIdentity());
        getDao().insert(limsBatchSample);
        return limsBatchSample.getId();
    }

    @Override
    public void insertSample(RestJsonWrapperBean wrapper) {
        LimsSampleBean sampleBean = wrapper.parseUnique(LimsSampleBean.class);
        String batchId = sampleBean.getExt$Item("batchId");
        String productId = sampleBean.getExt$Item("productId");
        if (productId == null || batchId == null) return;

        // 手动校验samplecode
        if (!StringUtils.isBlank(sampleBean.getSampleCode())) {
            LimsSampleBean exist = sampleService.selectFirstByFilter(SearchFilter.instance().match("sampleCode", sampleBean.getSampleCode()).filter(MatchPattern.EQ));
            if (exist != null && exist.getId() != null) {
                throw new InvalidDataException("样本编号已被占用，请更换！");
            }
        } else {
            return;
        }

        LimsBatchBean limsBatchBean = batchService.selectById(Long.parseLong(batchId));
        List<Long> productIdList = Arrays.stream(productId.split(","))
                .map(Long::parseLong).collect(Collectors.toList());
        sampleBean.setId(ApplicationContextHelper.getNextIdentity());
        sampleBean.setOriNo(sampleBean.getSampleCode());

        LimsBatchSampleBean batchSampleBean = new LimsBatchSampleBean();
        batchSampleBean.setId(ApplicationContextHelper.getNextIdentity());
        batchSampleBean.setBatchId(Long.parseLong(batchId));
        batchSampleBean.setBatchCode(limsBatchBean.getBatchCode());
        batchSampleBean.setSampleId(sampleBean.getId());
        batchSampleBean.setSampleCode(sampleBean.getSampleCode());

        List<LimsProductMainBean> productMainBeans = productMainService.selectListByIds(productIdList);
        List<LimsBatchSampleProductBean> productBeanList = new ArrayList<>();
        for (LimsProductMainBean productMainBean : productMainBeans) {
            LimsBatchSampleProductBean productBean = new LimsBatchSampleProductBean();
            productBean.setId(ApplicationContextHelper.getNextIdentity());
            productBean.setBatchId(Long.parseLong(batchId));
            productBean.setBatchCode(limsBatchBean.getBatchCode());
            productBean.setBatchSampleId(batchSampleBean.getId());
            productBean.setSampleId(sampleBean.getId());
            productBean.setSampleCode(sampleBean.getSampleCode());
            productBean.setProductId(productMainBean.getId());
            productBean.setProductCode(productMainBean.getProductCode());
            productBean.setProductName(productMainBean.getProductName());
            productBeanList.add(productBean);
        }

        sampleService.getDao().insert(sampleBean);
        getDao().insert(batchSampleBean);
        sampleProductService.getDao().insert(productBeanList);
    }

    @Override
    public void sampleChoose(RestJsonWrapperBean wrapper) {
        List<LimsSampleBean> sampleBeans = wrapper.parse(LimsSampleBean.class);
        String batchId = wrapper.getParamValue("batchId");
        String productCode = wrapper.getParamValue("productCode");
        if (productCode == null || batchId == null) return;
        LimsBatchBean limsBatchBean = batchService.selectById(Long.parseLong(batchId));
        List<String> productCodeList = Arrays.stream(productCode.split(",")).collect(Collectors.toList());
        List<LimsProductMainBean> productMainBeans = productMainService.getDao().selectListByOneColumnValues(productCodeList, "productCode");

        List<LimsBatchSampleBean> insetBatchSamples = new ArrayList<>();
        List<LimsBatchSampleProductBean> productBeanList = new ArrayList<>();
        for (LimsSampleBean sampleBean : sampleBeans) {
            LimsBatchSampleBean batchSampleBean = new LimsBatchSampleBean();
            batchSampleBean.setId(ApplicationContextHelper.getNextIdentity());
            batchSampleBean.setBatchId(Long.parseLong(batchId));
            batchSampleBean.setBatchCode(limsBatchBean.getBatchCode());
            batchSampleBean.setSampleId(sampleBean.getId());
            batchSampleBean.setSampleCode(sampleBean.getSampleCode());
            batchSampleBean.setSelected(Constant.YES);
            insetBatchSamples.add(batchSampleBean);

            for (LimsProductMainBean productMainBean : productMainBeans) {
                LimsBatchSampleProductBean productBean = new LimsBatchSampleProductBean();
                productBean.setId(ApplicationContextHelper.getNextIdentity());
                productBean.setBatchId(Long.parseLong(batchId));
                productBean.setBatchCode(limsBatchBean.getBatchCode());
                productBean.setBatchSampleId(batchSampleBean.getId());
                productBean.setSampleId(sampleBean.getId());
                productBean.setSampleCode(sampleBean.getSampleCode());
                productBean.setProductId(productMainBean.getId());
                productBean.setProductCode(productMainBean.getProductCode());
                productBean.setProductName(productMainBean.getProductName());
                productBeanList.add(productBean);
            }
        }
        getDao().insert(insetBatchSamples);
        sampleProductService.getDao().insert(productBeanList);
    }

    @Audit(AuditConstant.INSTANT_SAVE)
//    @AuditTrailEntry(AuditTrailType.UPDATE)
    @Override
    @Transactional
    public void updateSample(RestJsonWrapperBean wrapper) {
        LimsSampleBean sampleBean = wrapper.parseUnique(LimsSampleBean.class);

        // 手动校验samplecode
        if (!StringUtils.isBlank(sampleBean.getSampleCode())) {
            List<LimsSampleBean> exists = sampleService.selectListByFilter(SearchFilter.instance().match("sampleCode", sampleBean.getSampleCode()).filter(MatchPattern.EQ));
            if (exists.stream().anyMatch(es -> !es.getId().equals(sampleBean.getId()))) {
                throw new InvalidDataException("样本编号已被占用，请更换！");
            }
        } else {
            return;
        }

        String productChange = sampleBean.getExt$Item("productChange");

        // 2023-07-10 因为要样本编号也可以改，所以这里加上同步到订单样本、订单样本检测项目
        String batchSampleId = sampleBean.getExt$Item("batchSampleId");

        LimsBatchSampleBean bs = new LimsBatchSampleBean();
        bs.setSampleCode(sampleBean.getSampleCode());
        bs.setId(Long.parseLong(batchSampleId));
        getDao().update(bs, "sampleCode");

        LimsBatchSampleProductBean bsp = new LimsBatchSampleProductBean();
        bsp.setBatchSampleId(bs.getId());
        bsp.setSampleCode(sampleBean.getSampleCode());
        sampleProductService.getDao().update(bsp, Collections.singletonList("sampleCode"), "batchSampleId");

        sampleBean.setOriNo(sampleBean.getSampleCode());
        sampleService.getDao().updateIfChanged(sampleBean);

        // 产品发生变化的
        if ("1".equals(productChange)) {
            // 删除原来的产品
            LimsBatchSampleProductBean deleteBean = new LimsBatchSampleProductBean();
            deleteBean.setBatchSampleId(Long.parseLong(batchSampleId));
            sampleProductService.getDao().deleteBy(deleteBean, "batchSampleId");
            // 然后添加新产品
            String productId = sampleBean.getExt$Item("productId");
            List<Long> productIdList = Arrays.stream(productId.split(","))
                    .map(Long::parseLong).collect(Collectors.toList());
            List<LimsProductMainBean> productMainBeans = productMainService.selectListByIds(productIdList);
            List<LimsBatchSampleProductBean> productBeanList = new ArrayList<>();
            for (LimsProductMainBean productMainBean : productMainBeans) {
                LimsBatchSampleProductBean productBean = new LimsBatchSampleProductBean();
                productBean.setId(ApplicationContextHelper.getNextIdentity());
                productBean.setBatchId(Long.parseLong(sampleBean.getExt$Item("batchId")));
                productBean.setBatchCode(sampleBean.getExt$Item("batchCode"));
                productBean.setBatchSampleId(Long.parseLong(sampleBean.getExt$Item("batchSampleId")));
                productBean.setSampleId(sampleBean.getId());
                productBean.setSampleCode(sampleBean.getSampleCode());
                productBean.setProductId(productMainBean.getId());
                productBean.setProductCode(productMainBean.getProductCode());
                productBean.setProductName(productMainBean.getProductName());
                productBeanList.add(productBean);
            }
            sampleProductService.getDao().insert(productBeanList);
        }

    }

    @Override
    public Page<LimsSampleBean> selectBatchSampleInfo(RestJsonWrapperBean wrapper) {
        MapperParameter parameter = wrapper.extractMapFilter();
        PageRowBounds pageRowBounds = wrapper.extractPageRowBounds();
        return MybatisPageHelper.get(pageRowBounds, () -> getDao().selectBatchSampleInfo(parameter)
                .parallelStream().map(e -> PersistableHelper.mapToPersistable(e, LimsSampleBean.class))
                .collect(Collectors.toList()));
    }

    @Override
    public List<LimsSampleBean> selectBatchSample(MapperParameter parameter) {
        return getDao().selectBatchSampleInfo(parameter)
                .parallelStream().map(e -> PersistableHelper.mapToPersistable(e, LimsSampleBean.class))
                .collect(Collectors.toList());
    }


    @Transactional
    @Override
    public void deleteBatchSamples(RestJsonWrapperBean wrapper) {
        List<LimsSampleBean> parse = wrapper.parse(LimsSampleBean.class);
        List<Long> batchSampleIds = parse.stream().map(s -> s.getExt$Item("batchSampleId")).map(Long::parseLong).collect(Collectors.toList());
        List<LimsBatchSampleProductBean> productBeanList = new ArrayList<>();
        for (Long batchSampleId : batchSampleIds) {
            LimsBatchSampleProductBean productBean = new LimsBatchSampleProductBean();
            productBean.setBatchSampleId(batchSampleId);
            productBeanList.add(productBean);
        }
        sampleProductService.getDao().deleteBy(productBeanList, "batchSampleId");
        getDao().deleteByIdList(batchSampleIds);
        List<LimsSampleBean> deleteSamples = parse.stream().filter(s ->
                Constant.NO.equals(s.getExt$Item("selected"))).collect(Collectors.toList());
        sampleService.getDao().deleteBy(deleteSamples);
    }

    @Override
    public LimsSampleBean getBatchSampleInfo(Long id) {
        MapperParameter parameter = new MapperParameter();
        parameter.setFilter(SearchFilter.instance().match("batchSampleId", id).filter(MatchPattern.EQ));
        List<LimsSampleBean> sampleBeans = getDao().selectBatchSampleInfo(parameter)
                .parallelStream().map(e -> PersistableHelper.mapToPersistable(e, LimsSampleBean.class))
                .collect(Collectors.toList());
        return sampleBeans.isEmpty() ? null : sampleBeans.get(0);
    }

    @Override
    public Page<LimsSampleBean> selectBatchSampleInfos(RestJsonWrapperBean wrapper) {
        MapperParameter parameter = wrapper.extractMapFilter();
        PageRowBounds pageRowBounds = wrapper.extractPageRowBounds();
        return MybatisPageHelper.get(pageRowBounds, () -> getDao().selectBatchSampleInfos(parameter)
                .parallelStream().map(e -> PersistableHelper.mapToPersistable(e, LimsSampleBean.class))
                .collect(Collectors.toList()));
    }
}
